/* Orbas:
 *     A open source CORBA Specification implementation from Huihoo.
 *
 * Copyright 2002-2003 Huihoo.org, Inc. All Right Reserved.
 *
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 *
 * For more information, visit:
 *
 * http://www.huihoo.org/orbas
 */

package org.huihoo.orbas.orb.protocols.iiop;

/**
 * <p>Description: </p>
 * UDP broadcaster in LAN.
 * <p>Copyright (c) 2002,2003</p>
 * <p>Company: <a href="http://www.huihoo.org/">huihoo.org</a></p>
 * @author <a href="http://www.huihoo.org/~mep">mep(mep@huihoo.com)</a>
 * @see <a href="http://www.huihoo.org/orbas">http://www.huihoo.org/orbas</a>
 * @version 1.0
 */

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import org.huihoo.orbas.orb.ORB;
import org.huihoo.orbas.orb.protocols.ServerBroadcaster;
//import java.net.SocketTimeoutException;
//import java.net.InetSocketAddress;

public class IiopBroadcaster implements ServerBroadcaster {

	ORB orb;
	java.util.Hashtable tables = new java.util.Hashtable();
	boolean flag;

	public IiopBroadcaster(ORB orb) {
		this.orb = orb;
		flag = true;
	}

	public void binding(String name, org.omg.CORBA.Object obj)
			throws org.omg.CORBA.ORBPackage.InvalidName {

		String ref = null;

		try {
			ref = orb.object_to_string(obj);
		} catch (Exception e) {
		}

		tables.put(name, ref);
	}

	public void unbinding(String name) {
		tables.remove(name);
	}

	public org.omg.CORBA.Object resolveBinding(String name) {
		org.omg.CORBA.Object ret;

		// System.out.println("resolveBinding " + name);
		// get the reference from network
		byte[] request = name.getBytes();
		try {
			DatagramPacket packet = new DatagramPacket(request, request.length);

			DatagramSocket sock = new DatagramSocket();

			InetAddress destAddress = InetAddress.getLocalHost();

			packet.setAddress(destAddress);
			packet.setPort(Iiop.UDP_PORT);

			// sock.setBroadcast(true);

			sock.send(packet);

			byte[] data = new byte[1500];

			DatagramPacket reply = new DatagramPacket(data, data.length);

			sock.setSoTimeout(3000);

			// This call will block until a datagram arrives
			try {
				sock.receive(reply);
			} catch (IOException e) {
			}

			String ior = new String(reply.getData(), 0, reply.getLength());

			if (ior.startsWith("IOR:")) {
				return orb.string_to_object(ior);
			}
		} catch (java.net.SocketException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		} catch (java.net.UnknownHostException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		} catch (java.io.IOException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		}

		return null;

	}

	public void run() {

		// System.out.println("Broadcast thread started.");

		DatagramSocket sock;
		try {
			sock = new DatagramSocket(Iiop.UDP_PORT);
			// sock.setReuseAddress(true);
			// sock.bind(new InetSocketAddress(Iiop.UDP_PORT));

			while (flag) {
				byte[] data = new byte[1500];
				DatagramPacket packet = new DatagramPacket(data, data.length);

				// This call will block until a datagram arrives
				// System.out.println("Ready to resolve binding");
				sock.receive(packet);
				System.out.println("get resolve binding request");

				String message = new String(packet.getData(), 0,
						packet.getLength());

				// System.out.println("get resolve binding request " + message);

				// it is a server ior request
				// we create a reply
				String ret = (String) tables.get(message);
				if (ret == null) {
					continue;
				}

				byte[] retData = ret.getBytes();

				DatagramPacket reply = new DatagramPacket(retData,
						retData.length, packet.getAddress(), packet.getPort());

				// DatagramSocket replySock = new
				// DatagramSocket(packet.getSocketAddress());
				// replySock.setBroadcast(true);
				sock.send(reply);

			}
		} catch (java.net.SocketException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		} catch (java.net.UnknownHostException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		} catch (java.io.IOException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		}

	}

	public void shutdown() {
		flag = false;
	}
}
